#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include <modbus/modbus.h>
#include <iostream>

int main(void)
{
    modbus_t *ctx;
    /* TCP */
    //指定服务器地址与端口号
    ctx = modbus_new_tcp("127.0.0.1", 1502);
    modbus_set_debug(ctx, TRUE);

    //与服务器建立连接
    if (modbus_connect(ctx) == -1)
    {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    /*1.  写单个线圈 */
    // 使用功能码0x05(写入单个线圈) 在地址addr上写值tab_rq_bits[0] 值为true or false, 成功返回1，失败返回-1;
    // addr 为相对地址: 0 - 65535 绝对地址范围: 000001-065536
    // 0xFF00 1: 置位, 0x0000 0: 复位
    int coil_addr = 9;
    int res = modbus_write_bit(ctx, coil_addr, 1);
    if (res == 1)
    {

        uint8_t *data_read = (uint8_t *)malloc(1 * sizeof(uint8_t));
        memset(data_read, 0, 1 * sizeof(uint8_t));
        /*2. 读多个线圈 */
        //使用功能码0x01(读取输出线圈)，读取 1 个位（线圈)的状态到读取到地址addr, 并存储到data_read,成功返回读到的数量，失败返回-1
        int data_number = modbus_read_bits(ctx, coil_addr, 1, data_read);
        std::cout << "number: " << data_number << " data: " << unsigned(data_read[0]) << std::endl;
        free(data_read);
    }
    else //-1
    {
        std::cout << "error" << std::endl;
    }

    /*2. 写多个线圈*/
    //使用功能码0x0F(写入多个线圈),从数组写nb个位（线圈）到地址coils_addr

    int coils_addr = 9;
    int nb = 5;
    uint8_t *bits_save = (uint8_t *)malloc(nb * sizeof(uint8_t));
    memset(bits_save, 0, nb * sizeof(uint8_t));
    res = modbus_write_bits(ctx, coils_addr, nb, bits_save);
    if (res == nb)
    {
        res = modbus_read_bits(ctx, coils_addr, nb, bits_save);
        free(bits_save);
    }
    else
    {
        std::cout << "error" << std::endl;
    }

    /*3. 写单个寄存器*/
    // addr 为相对地址: 0-65535 绝对地址范围: 400001-465535
    int register_addr = 9;
    uint16_t *register_write = (uint16_t *)malloc(sizeof(uint16_t));
    memset(register_write, 0, sizeof(uint16_t));
    res = modbus_write_register(ctx, register_addr, register_addr);
    if (res == 1)
    {
        res = modbus_read_registers(ctx, register_addr, 1, register_write);
        free(register_write);
    }
    else
    {
        std::cout << "error" << std::endl;
    }

    /*4. 写多个寄存器**/
    res = modbus_write_registers(ctx, register_addr, nb, register_write);
    if (res == nb)
    {
        res = modbus_read_registers(ctx, register_addr, nb, register_write);
    }
    else
    {
        std::cout << "error" << std::endl;
    }
    /* Close the connection */
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}